import json

from elasticsearch import Elasticsearch, helpers
from tqdm import tqdm
import time
import re
import unicodedata

class ElasticsearchHandler():
    '''ES客户端，用于排重'''

    def __init__(self):
        self.tianyi_ip = ['10.23.2.21', '10.23.2.22', '10.23.2.23']
        self.tianyi_port = '9200'
        self.tianyi_index = 'simba_online'
        self.server = [{'host': i, 'port': self.tianyi_port} for i in self.tianyi_ip]
        self.index = self.tianyi_index
        print(self.server, self.index)
        # elasticsearch 对象
        self.es = Elasticsearch(hosts=self.server)

    def lsearch(self, query):
        '''数据量较大'''
        result = helpers.scan(client=self.es, index=self.index, query=query, scroll='5m')
        return result

    def search(self, query):
        result = self.es.search(index=self.index, body=query, preference='primary_first')['hits']['hits']
        return result

    def count(self, query):
        result = self.es.count(index='new_sim_fp_online', body=query, preference='primary_first')
        return result.get('count', 0)


def remove_punctuation(line, strip_all=True):
    if strip_all:
        rule = re.compile(r"[^a-zA-Z0-9\u4e00-\u9fa5]")
        line = rule.sub('', line)
    else:
        punctuation = """！？｡＂＃＄％＆＇（）＊＋－／：；＜＝＞＠［＼］＾＿｀｛｜｝～｟｠｢｣､、〃》「」『』【】〔〕〖〗〘〙〚〛〜〝〞〟〰〾〿–—‘'‛“”„‟…‧﹏"""
        re_punctuation = "[{}]+".format(punctuation)
        line = re.sub(re_punctuation, "", line)
    return line.strip()


def findLength(A, B) -> int:
    A = remove_punctuation(A)
    B = remove_punctuation(B)

    def maxLength(addA: int, addB: int, length: int) -> int:
        ret = k = 0
        for i in range(length):
            if A[addA + i] == B[addB + i]:
                k += 1
                ret = max(ret, k)
            else:
                k = 0
        return ret

    n, m = len(A), len(B)
    ret = 0
    for i in range(n):
        length = min(m, n - i)
        ret = max(ret, maxLength(i, 0, length))
    for i in range(m):
        length = min(n, m - i)
        ret = max(ret, maxLength(0, i, length))
    return ret


pat = re.compile(r'原标题|来源')


class Data:
    def __init__(self):
        self.es = ElasticsearchHandler()
        # '搞笑'
        self.cls = {'科技', '职场', '房产', '情感', '国际', '体育', '游戏', '美食', '汽车', '三农', '时尚', '娱乐', '育儿', '动漫', '科学',
                    '旅游', '文化', '动物', '天气', '教育', '时政', '军事', '数码', '摄影', '健康', '财经', '社会', '家居', '星座', '历史'}
        self.cls2 = {'化学', '相声小品', '体育花边', '新酷数码产品', '口腔护理', '城市介绍', '国际军事', '车展', '自行车', '相机', '房产资讯', '戏剧曲艺', '国内游',
                     '日本动漫', '时尚资讯', '电影', '人车生活', '铁人三项', '用车养车', '军事周边', '泛娱乐', '举重', 'K12', '恋爱', '汽车技术', '行情报价',
                     '射击', '天文航天', '亲情', '酒店', '搏击', '极限运动', '财经人物', '健康行业资讯', '期货', '时尚穿搭', '电脑', '留学', '求职就业', '社会治安',
                     '赛艇', '婆媳关系', '家庭矛盾', '跳水', '餐饮行业', '互联网金融', '汽车服务', '儿童教育', '疾病', '高考', '汽车金融', '田径', '外汇',
                     '教育资讯', '武器装备', '试驾评测', '农业', '摔跤', '宏观调控', '法制社会', '娱乐明星', '动漫资讯', '信托', '摩托车', '游戏产品', '旅游新闻',
                     '体操', '国际经济', '文化人物', '搞笑段子', '摄影活动', '保险', '美食探店', '摄影知识', '中国外交', '宠物', '时尚单品', '手机', '电子竞技',
                     '农村', '心理测试', '科技人物', '新能源汽车', '宏观经济', '自驾游', '改装/赛事', '饮品', '音乐', '户外', '社会冲突', '台球', '明星周边',
                     '科学资讯', '儿童健康', '国产动漫', '人工智能', '赛车', '违法犯罪', '外国文化', '正能量', '美妆护肤', '柔道', '工业技术', '星座分析', '通信产业',
                     '命理分析', '素人', '民生', '植物学', '电视剧', '城市建设', '政府政务', 'VRAR', '中国历史', '摄影作品', '乒乓球', '股票', '学前教育',
                     '汽车花边', '大数据', '学历教育', '世界史', '政策法规', '互联网', '跆拳道', '时装周', '羽毛球', '棋牌', '职业心得', '足球', '自然灾害',
                     '家居风水', '安全事故', '农民', '橄榄球', '不文明行为', '中医中药', '疫情', '医学', '物业', '银行', '学车', '动物学', '军情', '交通事故',
                     '宝宝取名', '马术', '美国动漫', '国际政治', '境外游', '财经行业动态', '动物新闻', '二手车', '友情', '艺术', '航空航天', '婴幼儿喂养', '生育观念',
                     '会议', '射箭', '棒球', '职场管理', '科学家', '房屋买卖', '生鲜食材', '宗教', '健身减肥', '动漫周边', '排球', '甜品烘焙', '英语教育',
                     '党内廉政', '居家生活', '纪录片', '健康养生', '备孕', '互联网创业', '基金', '机器学习', '贵金属', '航海', '体彩', '特色美食', '产后养护',
                     '房屋租赁', '人文', '婚姻情感', '击剑', '生物学', '开发技术', '债券', '汽车行业新闻', '汽车导购', '周易', '传统文化', '育儿生活', '二级分类',
                     '交通出行', '高尔夫', '港澳台西新', '游泳', '冰雪', '地理学', '摄影文化', '厨艺教程', '孕期保健', '物理学', '国际社会', 'COSPLAY', '皮划艇',
                     '收藏', '社会百态', '综合赛事', '汽车文化', '国家发展', '急救知识', '跑步', '心灵鸡汤', '新车', '篮球', '游戏产业', '综艺', '网球', '明星名人',
                     '机票', '家庭教育', '职场周边', '装修'}

    def Tversky(self, list_1, list_2):
        if not list_1 or not list_2: return 0.0
        inter = float(len(set(list_1).intersection(set(list_2))))  # 交集
        l1_except = float(len(set(list_1).difference(set(list_2))))  # 在l1不在l2
        l2_except = float(len(set(list_2).difference(set(list_1))))  # 在l2不在l1
        return inter / (inter + l1_except + l2_except) if inter else 0

    def getdata(self, classes=None):
        resd = open('alltraindata.txt', 'a+', encoding='utf-8')
        for classes in tqdm(self.cls):
            count = 50000
            if classes in {'科技', '游戏', '三农', '娱乐', '数码', '财经', '历史', '财经'}:
                count += 50000
            elif classes in {'国际', '社会', '体育', '时政', '军事'}:
                count += 100000
            query = {
                '_source': ['dataid', 'title', 'supervise_topic', 'title_fp', 'content_fp', 'group_id',
                            'classes_v2', 'sub_classes_v2', 'content'],
                "query": {"bool": {"must": [
                    {"match": {"toutiaoIdx": 1}},
                    {"match": {"docType": 'news'}},
                    {"term": {'classes_v2': classes}},
                    # {'range': {'ctime': {'lte': int(time.time() - 86400 * 30 * 12)}}},
                ]}},
                "aggs": {"uid_aggs": {"cardinality": {"field": "group_id"}}}
            }
            res = self.es.lsearch(query=query)
            time.sleep(60)
            tmp_count = 0
            cache = []
            for i in res:
                if len(cache) > 200: cache = cache[-150:]
                title = i.get('_source', {}).get('title', '')
                flag = False
                for ot in cache:
                    if self.Tversky(ot, title) > 0.1:
                        flag = True
                        break
                if flag: continue
                cache.append(title)
                dataid = i.get('_id')
                content = i.get('_source', {}).get('content', '').replace('\r', '').replace('\n', '').replace('\r\n',
                                                                                                              '').replace(
                    ' ', '')
                con = content.strip().split('。')
                best = 0
                bestt = ''
                for cline in con:
                    sline = cline.strip().split('，')
                    for idx in range(len(sline) - 2):
                        score = self.Tversky(title, ''.join(sline[idx:idx + 2]))
                        if pat.search(''.join(sline[idx:idx + 2])): continue
                        if score > best:
                            best = score
                            bestt = ','.join(sline[idx:idx + 2])
                if best > 0.3 and best < 0.6:
                    comsub = findLength(title, bestt)
                    score = round(max(comsub / len(title), comsub / len(bestt)), 4)
                    if score > 0.5: continue
                    if not dataid or len(classes) != 2 or not title or not bestt: continue
                    if abs(len(title) - len(bestt)) > 20: continue
                    resd.write('\t'.join([dataid, classes, title, bestt]) + '\n')
                    tmp_count += 1
                    if tmp_count > count:
                        break

    def test(self, classes=None):
        print(len(self.cls2))
        for classes in self.cls:
            count = 10
            if classes in {'科技', '游戏', '三农', '娱乐', '数码', '财经', '历史', '财经'}:
                count += 10
            elif classes in {'国际', '社会', '体育', '时政', '军事'}:
                count += 10
            query = {'size': 100,
                     '_source': ['dataid', 'title', 'supervise_topic', 'title_fp', 'content_fp', 'group_id',
                                 'classes_v2', 'sub_classes_v2', 'content'],
                     "query": {"bool": {"must": [
                         # {"match": {"toutiaoIdx": 1}},
                         {"match": {"docType": 'news'}},
                         {"term": {'classes_v2': classes}},
                         {'range': {'ctime': {'lte': int(time.time() - 86400)}}},
                     ]}},
                     "aggs": {"uid_aggs": {"cardinality": {"field": "group_id"}}}
                     }
            res = self.es.search(query=query)
            tmp_count = 0
            cache = []
            for i in res:
                if len(cache) > 100: cache = cache[-90:]
                title = i.get('_source', {}).get('title', '')
                title = unicodedata.normalize('NFKC', title)
                flag = False
                for ot in cache:
                    if self.Tversky(ot, title) > 0.1:
                        flag = True
                        break
                if flag: continue
                cache.append(title)
                dataid = i.get('_id')
                content = i.get('_source', {}).get('content', '').replace('\r', '').replace('\n', '').replace('\r\n',
                                                                                                              '').replace(
                    ' ', '')
                con = content.strip().split('。')
                best = 0
                bestt = ''
                for cline in con:
                    sline = cline.strip().split('，')
                    for idx in range(len(sline) - 2):
                        simtitle = unicodedata.normalize('NFKC', ','.join(sline[idx:idx + 2]))
                        score = self.Tversky(title, simtitle)
                        if pat.search(''.join(sline[idx:idx + 2])): continue
                        if score > best:
                            best = score
                            bestt = simtitle
                if best > 0.4 and best < 0.7:
                    comsub = findLength(title, bestt)
                    score = round(max(comsub / len(title), comsub / len(bestt)), 4)
                    if score > 0.4: continue
                    if not dataid or len(classes) != 2 or not title or not bestt: continue
                    if abs(len(title) - len(bestt)) > 20: continue
                    # print('\t\t'.join([str(score),str(best), classes, title, bestt]))
                    print('\t\t'.join([str(comsub), str(score), str(len(title) - len(bestt)), classes, title, bestt]))
                #     tmp_count += 1
                #     if tmp_count > count:
                #         break


if __name__ == '__main__':
    # test()
    data = Data()
    # data.getdata()
    data.test()
    # cache = set()
    # resdata = open('new_seed1.txt', 'a+', encoding='utf-8')
    # for i in tqdm(data.getdata()):
    #     gid = i.get('_source').get('group_id')
    #     did = i.get('_id')
    #     if gid in cache: continue
    #     cache.add(gid)
    #     line = {'ori': i.get('_source')}
    #     resdata.write(json.dumps(line, ensure_ascii=False) + '\n')
